// XXX size_t
// ctypes also has c_wchar, c_wchar_p

int is_tuple(int type)
{
    return ERL_SMALL_TUPLE_EXT == type || ERL_LARGE_TUPLE_EXT == type;
}

#define DEF_DECODE(TYPE, TARGET_TYPE)                             \
int ei_decode_ ## TYPE (const char* buf, int* pindex, TYPE* val)  \
{                                                                 \
    TARGET_TYPE x;                                                \
    ZERO(ei_decode_ ## TARGET_TYPE(buf, pindex, &x));             \
    if ( x > TYPE ## _MAX || x < TYPE ## _MIN ) return -1;        \
    *val = (TYPE)x;                                               \
    return 0;                                                     \
}

DEF_DECODE(sint8, long);
DEF_DECODE(uint8, ulong);
DEF_DECODE(sint16, long);
DEF_DECODE(uint16, ulong);
DEF_DECODE(sint32, long);
DEF_DECODE(uint32, ulong);
DEF_DECODE(sint64, longlong);
DEF_DECODE(uint64, ulonglong);
DEF_DECODE(int, long);

int ei_decode_pointer(const char* buf, int* pindex, pointer* ptr)
{
    if ( sizeof(pointer)==sizeof(long) )
    {
        return ei_decode_ulong(buf, pindex, (ulong*)ptr);
    }
    else if ( sizeof(pointer)==sizeof(long long) )
    {
        return ei_decode_ulonglong(buf, pindex, (ulonglong*)ptr);
    }
    else return -1;
}

int ei_encode_pointer(char* buf, int* pindex, pointer ptr)
{
    if ( sizeof(pointer) == sizeof(ulong) )
    {
        return ei_encode_ulong(buf, pindex, (ulong)ptr);
    }
    else if ( sizeof(pointer) == sizeof(ulonglong) )
    {
        return ei_encode_ulonglong(buf, pindex, (ulonglong)ptr);
    }
    else return -1;
}

int ei_decode_float(const char* buf, int* pindex, float* val)
{
    double x;
    ZERO(ei_decode_double(buf, pindex, &x));
    *val = (float)x;
    return 0;
}

int ei_decode_longdouble(const char* buf, int* pindex, longdouble* val)
{
    double x;
    ZERO(ei_decode_double(buf, pindex, &x));
    *val = x;
    return 0;
}

int ei_encode_size_t(char* buf, int* pindex, size_t val)
{
    if ( sizeof(size_t) == sizeof(ulong) )
    {
        return ei_encode_ulong(buf, pindex, (ulong)val);
    }
    else if ( sizeof(size_t) == sizeof(ulonglong) )
    {
        return ei_encode_ulonglong(buf, pindex, (ulonglong)val);
    }
    else return -1;
}
